<?php

namespace App\Jobs;

use App\Exceptions\Arr;
use App\Models\Appoint;
use App\Models\AppointNum;
use App\Models\Hospital;
use App\Models\HospitalAppoint;
use App\Models\HospitalAppointType;
use App\Models\SystemNotice;
use App\Models\TempPushRecord;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class AppointList implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $appoint;
    protected $is_success = true;
    public $tries = 0;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(Appoint $appoint)
    {
        $this->appoint = $appoint;
        $this->onQueue('appoint');
        $this->onConnection('redis');
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
//        if($this->appoint->status == 6)
//        {
//            $this->appoint->status = 1;
//            $this->appoint->save();
//        }else {
//        }
        $appoint = $this->appoint;
        if(false){
            $this->fail('任务已处理，重复提交');
        }else {
            try {
                DB::beginTransaction();
                $hospitalAppoint = HospitalAppoint::query()
                    ->where('hospital_id',$appoint->hospital_id)
                    ->where('type',$appoint->type)
                    ->where('is_open',1)
                    ->first();
                if(!$hospitalAppoint){
                    $this->failed("时间段号源未设置");
                    return ;
                }
                //时间段总数
                $appoints = Appoint::query()
                    ->where([
                        'hospital_id' => $appoint->hospital_id,
                        'type' => $appoint->type,
                        'appoint_date' => $appoint->appoint_date,
                        'source' => 1,
                        'status' => 1
                    ])
                    ->where('id','!=',$appoint->id)
                    ->lockForUpdate()
                    ->get();
                Log::info($appoints);
                $appointsArr = $appoints->toArray();
                $appointMax = AppointNum::query()->where([
                    'hospital_id' => $appoint->hospital_id,
                    'appoint_type' => $appoint->type,
                    'interval_id' => $appoint->appoint_time,
                    'date' => $appoint->appoint_date
                ])->first();
                if (!$appointMax) {
                    $this->failed("时间段号源未设置");
                    return ;
                }
                //时间段已约数量
                $intervalNum = array_filter($appointsArr, function ($where) use ($appoint) {
                    return $where['appoint_time'] == $appoint->appoint_time;
                });
                Log::info("数组：");
                Log::info($intervalNum);


                if (isset($appointMax) && $appointMax->interval_num != -1 && $appointMax->interval_num < count($intervalNum)) {
                    $this->failed("时间段号源已约满");
                    return ;
                }

                //如果不是体检且设置了子项则判断子项排班
                if ($appoint->project && $appoint->type != 1) {
                    $projectMax = AppointNum::query()->where([
                        'hospital_id' => $appoint->hospital_id,
                        'appoint_type' => $appoint->type,
                        'interval_id' => $appoint->appoint_time,
                        'date' => $appoint->appoint_date,
                        'project' => $appoint->project
                    ])->first();
                    if(!$projectMax){
                        $this->failed("该子项未设置排班");
                        return ;
                    }
                    //已约子项数量
                    $projectNum = array_filter($appointsArr, function ($where) use ($appoint) {
                        return $where['project'] == $appoint->project;
                    });

                    if ($projectMax && $projectMax->project_num != -1 && $projectMax->project_num < count($projectNum)) {
                        $this->failed("子项目号源已满");
                        return ;
                    }
                    //已约时间段子项目已约数量
                    $projectIntervalNum = array_filter($appointsArr, function ($where) use ($appoint) {
                        return $where['project'] == $appoint->project && $where['appoint_time'] == $appoint->appoint_time;
                    });

                    if ($projectMax && $projectMax->project_interval_num != -1 && $projectMax->project_interval_num < count($projectIntervalNum)) {
                        $this->failed("子项目时间段号源已满");
                        return ;
                    }
                }
                $this->success();
            } catch (\Exception $exception) {
                $this->fail($exception->getMessage());
            }
        }
    }
    public function failed($value="")
    {
        $this->is_success = false;
        $this->appoint->status = 7;
        $this->appoint->cancel = $value;
        $this->appoint->save();
        DB::commit();

        $systemNotice = new SystemNotice();
        $systemNotice->title = "预约失败";
        $systemNotice->content = "尊敬的用户您好，您提交的预约：".$this->appoint->appoint_date."'".$this->appoint->appointType->name."'由于号源已满未预约成功，请您选择其他时间";
        $systemNotice->type_id = 8;
        $systemNotice->user_id = $this->appoint->user_id;
        $systemNotice->save();

        $tempPushRecord = TempPushRecord::createTemp($this->appoint->user_id,3);
        TempPush::dispatch($tempPushRecord,$this->appoint);
    }

    public function success()
    {
        $this->is_success = true;
        $this->appoint->status = 1;
        $this->appoint->save();
        DB::commit();
        $systemNotice = new SystemNotice();
        $systemNotice->title = "预约成功";
        $systemNotice->content = "尊敬的用户您好，您提交的预约：".$this->appoint->appoint_date."'".$this->appoint->appointType->name."'已成功";
        $systemNotice->type_id = 7;
        $systemNotice->user_id = $this->appoint->user_id;
        $systemNotice->save();
        $tempPushRecord = TempPushRecord::createTemp($this->appoint->user_id,2);
        TempPush::dispatch($tempPushRecord,$this->appoint);
    }
//    /**
//     * 获取作业的唯一 ID。
//     */
//    public function uniqueId(): string
//    {
//        return $this->appoint->hospital_id."-".$this->appoint->type;
//    }

    /**
     * 同一条数据同一时间只处理一次。
     *
     * @return array<int, object>
     */
    public function middleware(): array
    {
        return [(new WithoutOverlapping($this->appoint->id))->dontRelease()];
    }
}
